<?php

/**
 * Class Login_service 用户登录相关业务逻辑
 * @author: Calvin
 * @email : hongbinfu@163.com
 * @readme: 用户注册业务逻辑处理类
 */
class Login_service extends MY_Service
{

    public $login_uid;

    public $user_info_session_key;
    public $auto_login_cookie_key;
    public $tryout_cookie_key;
    public $is_tryout_session_key;
    //private $login_log_key="LOGIN_LOG_ID";
    const LOGIN_LOG_KEY="LOGIN_LOG_ID";
    //private $last_active_key="__ACTIVE__";
    const LAST_ACTIVE_KEY = "__ACTIVE__";
    const OAUTH_USER_KEY="__OAUTH_USER_INFO__";

    public function __construct()
    {
        parent::__construct();
        $this->load->model('user_model');
        $this->config->load("user");
        $this->lang->load("user");

        //session或cookie的key
        $this->user_info_session_key = $this->config->item("user_info_session_key","login");
        $this->auto_login_cookie_key = $this->config->item("auto_login_cookie_key","login");
        $this->tryout_cookie_key = $this->config->item("tryout_cookie_key","login");
        $this->is_tryout_session_key = $this->config->item("is_tryout_session_key","login");
        $this->fast_login_keys = $this->config->item("fast_login_keys","user_common");
    }

    /**
     * 根据邮箱和密码来检查用户登陆
     * @param $email
     * @param $pwd
     */
    public function check_login_by_email($email,$pwd){
        $where = array(
            "email"=>$email
        );
        $user_info =  $this->user_model->get_user_info($where,"*");
        return $this->check_login($user_info,$pwd);
    }

    /**
     * 通过手机查找用户登录
     * @param $phone
     * @param $pwd
     * @return mixed
     */
    public function check_login_by_phone($phone,$pwd)
    {
        $where = array(
            "mobile"=>$phone
        );
        $user_info =  $this->user_model->get_user_info($where,"*");
        return $this->check_login($user_info,$pwd);
    }

    /**
     * 通过邮件查找用户登录
     * @param $email
     * @return bool
     */
    public function login_by_email($email)
    {
        $where = array(
            "email"=>$email
        );
        $user_info =  $this->user_model->get_user_info($where,"*");
        return $this->login_by_data($user_info,0,0);
    }

    /**
     * 通过授权信息查找用户登录
     */
    public function login_by_auth($auth_info){

        /*array(
            'from' => 1,
            'openid' => $me->openid,
            'name' => $user->nickname,
            'head_img' => $user->figureurl,
            'access_token' => $token->access_token,
            'expires_date' => $token->expires,
            'refresh_token' => $token->refresh_token unionid
        )*/
        $this->session->unset_userdata($this->user_info_session_key);
        $check = isset($auth_info['unionid']) && !empty($auth_info['unionid']);
        $key = $check ? "unionid":"openid";
        $auth_db_info =  $this->user_model->get_auth_user($auth_info[$key],$auth_info['from'],$key);
        $ip_address = $this->input->ip_address();
        $time = time();
        if(empty($auth_db_info)){

            $uid = $this->get_user_info("id");
            if(empty($uid)){
                $uid = 0;
            }
            $add_data = array(
                'from' => $auth_info['from'],
                'openid' => $auth_info['openid'],
                'name' => $auth_info['name'],
                'head_img' => $auth_info['head_img'],
                'access_token' => $auth_info['access_token'],
                'expires_date' => $auth_info['expires_date'],
                'refresh_token' => $auth_info['refresh_token'],
                'unionid' => isset($auth_info['unionid'])?$auth_info['unionid']:"",
                "creation_ts"=>$time,
                "lasttime"=>$time,
                "lastip"=>$ip_address,
                "login_times"=>$time,
                "status"=>1,
                "uid"=>$uid
            );
            $add = $this->user_model->add_auth_user($add_data);
            if(!$add){
                return $this->set_error(1002);
            }
            $auth_db_info = array_merge($add_data,$auth_info);
            $auth_db_info['id']= $this->user_model->get_insert_id();
        }else{
            $edit_data = array(
                'from' => $auth_info['from'],
                'openid' => $auth_info['openid'],
                'name' => $auth_info['name'],
                'head_img' => $auth_info['head_img'],
                'access_token' => $auth_info['access_token'],
                'expires_date' => $auth_info['expires_date'],
                'refresh_token' => $auth_info['refresh_token'],
                'unionid' => isset($auth_info['unionid'])?$auth_info['unionid']:"",
                "lasttime"=>$time,
                "lastip"=>$ip_address,
                "login_times"=>$time
            );
            //$data = array_merge($edit,$auth_info);
            $edit = $this->user_model->update_auth_user($auth_db_info['id'],$edit_data);
            if(!$edit){
                return $this->set_error(1002);
            }
            $auth_db_info = array_merge($auth_db_info,$edit_data);
            //$auth_db_info = array_merge($auth_db_info,$auth_info);
        }

        isset($auth_info['client_id']) && $auth_db_info['client_id'] = $auth_info['client_id'];
        $this->session->set_userdata(self::OAUTH_USER_KEY, $auth_db_info);
        return $auth_db_info;

    }

    /**
     * 检查手机是否被绑定
     * @param $phone
     * @param $from
     * @return bool
     */
    public function check_bind_by_phone($phone,$from){
        if(empty($phone) || empty($from)){
            return $this->set_error(1003);
        }
        $info = $this->user_model->get_auth_info_by_phone($phone,$from);
        if($info){
            return $this->set_error(5024);
        }else{
            return TRUE;
        }
    }

    /**
     * 检查用户是否被绑定第三方平台
     * @param $uid
     * @param $from
     * @return bool
     */
    public function check_auth_bind($uid,$from){
        $where = array(
            "uid"=>$uid,
            "from"=>$from
        );
        $info = $this->user_model->get_auth_info($where);

        if($info){
            return $this->set_error(5024);
        }else{
            return TRUE;
        }
    }

    /**
     * 检查openid是否已经绑定本平台用户
     * @param $openid
     * @param $from
     * @return bool
     */
    public function check_openid_bind($openid,$from){
        $where = array(
            "openid"=>$openid,
            "from"=>$from
        );
        $info = $this->user_model->get_auth_info($where);

        if($info){
            return $this->set_error(5024);
        }else{
            return TRUE;
        }
    }

    public function bind_auth_user($id,$uid,$from){

        $check = $this->check_auth_bind($uid,$from);
        if(!$check){
            return FALSE;
        }
        $bind = $this->user_model->update_auth_user($id,array("uid"=>$uid,"bind_ts"=>time()));
        if(!$bind){
            return $this->set_error(1002);
        }
        return TRUE;
    }

    /**
     * 获取授权信息
     * @return null
     */
    public function get_oauth_info(){
        $info = $this->session->userdata(self::OAUTH_USER_KEY);
        return !empty($info) ? $info : NULL;
    }


    public function clear_oauth_info(){
        $this->session->unset_userdata(self::OAUTH_USER_KEY);
        return TRUE;
    }

    /**
     * 检查用户登陆
     * @param $user_info
     * @return mixed
     */
    private function check_login($user_info,$pwd)
    {
        if(empty($user_info))
        {
            //用户不存在
            return $this->set_error(5004);
        }
        else if(empty($pwd))
        {
            //密码不能为空
            return $this->set_error(5003);
        }
        else if($user_info['status']==0)
        {
            //用户被禁用
            return $this->set_error(5005);
        }
        else if($user_info['verify']==0)
        {
            //用户未激活
            return $this->set_error(5006);
        }
        else if($user_info['password']!=md5($pwd))
        {
            //密码错误
            return $this->set_error(5002);
        }
        return $user_info;
    }

    /**
     * 获取用户信息（会话中）
     * @param string $find
     * @return string
     */
    public function get_user_info($find=""){
        $user_info = $this->session->userdata($this->user_info_session_key);
        if(empty($user_info)){
            return null;
        }
        if(!empty($find) && isset($user_info[$find]))
        {
            return $user_info[$find];
        }
        else
        {
            return $user_info;
        }
    }

    /**
     *
     * 加载用户信息到会话
     * @param $data
     */
    public function load_user_info($data)
    {
        if(!$this->is_tryout())
        {
            $data['last_active']=time();
            $name = !empty($data['nickname'])?$data['nickname']:(!empty($data['mobile'])?$data['mobile']:$data['email']);
            if(!empty($name))
            {
                $this->input->set_cookie(self::LAST_ACTIVE_KEY,$name."|".$data['last_active'],0,"","/");
            }
        }
        $this->session->set_userdata($this->user_info_session_key,$data);
        return TRUE;
    }

    public function refresh_user_info($key="",$value="")
    {
        $user_info = $this->get_user_info();
        if(empty($user_info))
        {
            return FALSE;
        }
        if(!empty($key) && is_array($key))
        {
            $user_info = array_merge($user_info,$key);
        }
        else if(!empty($key))
        {
            $user_info[$key]=$value;
        }
        $this->load_user_info($user_info);
        return $user_info;
    }

    /**
     * 重新加载用户信息到会话
     * @param $data
     */
    public function reload_user_info()
    {
        $old_user_info = $this->get_user_info();
        if(empty($old_user_info))
        {
            return false;
        }
        else
        {
            $user_info = $this->user_model->get_user_info(array("id"=>$old_user_info['id']),"*");
            $log_id = $old_user_info[self::LOGIN_LOG_KEY];
            $user_info[self::LOGIN_LOG_KEY]=$log_id;
            $this->load_user_info($user_info);
            return $user_info;
        }
    }

    /**
     * 第三方登陆
     * @param $uid
     * @param int $from 微信 / QQ
     * @param int $regular 试用用户(已不支持试用)
     * @return bool
     */
    public function login_by_uid($uid,$from=0,$regular=1){
        $user_info = $this->user_model->get_user_info(array("id"=>$uid),"*");
        $log_id = $this->add_login_log($user_info['id'],$from,$regular);
        if($log_id===false)
        {
            return false;
        }
        $user_info[self::LOGIN_LOG_KEY] = $log_id;
        $this->load_user_info($user_info);
        return true;
    }
    public function login_by_data($data,$from=0,$regular=1)
    {
        $log_id = $this->add_login_log($data['id'],$from,$regular);
        if($log_id===false)
        {
            return false;
        }
        $data[self::LOGIN_LOG_KEY] = $log_id;
        $this->load_user_info($data);
        return true;
    }

    /**
     * 退出
     */
    public function logout(){
        $user_info = $this->session->userdata($this->user_info_session_key);
        $this->input->set_cookie(self::LAST_ACTIVE_KEY,'',time()-3600,"","/");
        if(empty($user_info))
        {
            return true;
        }
        else
        {
            $data=array(
                'logout_ts' => time()
            );
            $this->user_model->update_login_log_by_id($user_info[self::LOGIN_LOG_KEY],$data);
            //销毁session
            $this->session->unset_userdata($this->user_info_session_key);
            $this->session->unset_userdata(self::LAST_ACTIVE_KEY);
            $this->session->unset_userdata(self::OAUTH_USER_KEY);
            $this->unset_auto_login();
            $this->unset_tryout();
            return true;
        }
    }

    /**
     * 是否已经登陆
     */
    public function is_login()
    {
        $user_info =  $this->session->userdata($this->user_info_session_key);
        $exp =$this->config->item("no_operation_exp_time","login");
        if(empty($user_info))
        {
            $this->logout();
            return $this->set_error(1011);
        }
        //正式用户未做任何操作2个小时候自动退出登录
        else if(!$this->is_tryout() && time()-$user_info['last_active']>$exp)
        {
            $this->logout();
            return $this->set_error(1011);
        }
        else
        {
            return $this->refresh_user_info();
        }
    }



    public function is_auto_login(){
        return $this->input->cookie($this->auto_login_cookie_key);
    }

    public function unset_auto_login(){
        $this->input->set_cookie($this->auto_login_cookie_key, '', time()-3600,'', '/');
        return true;
    }
    /**
     * 自动登录
     * @return bool
     */
    public function auto_login()
    {
        $auto = $this->is_auto_login();
        if($auto)
        {
            $user_info = $this->user_model->get_user_info_by_uniqid($auto,"*");
            if(!empty($user_info) && $user_info['account_type']!==0)
            {
                return $this->login_by_data($user_info);
            }
        }
        $this->unset_auto_login();
        return false;

    }

    /**
     * 添加自动登录行为
     */
    public function add_auto_login($uid){
        $uniqid = Common::uniqid();
        $exp = $this->config->item('auto_login_exp_time','login');
        $this->input->set_cookie($this->auto_login_cookie_key,$uniqid,$exp,'', '/');
        $data = array(
            "uniqid" => $uniqid
        );
        $edit = $this->user_model->update($uid,$data);
        if($edit === false)
        {
            return $this->set_error(1002);
        }
        else
        {
            return true;
        }
    }

    /**
     * 登录日志
     * @param $uid 用户id
     * @param int $from 用户来源
     * @param int $regular 是否试用用户
     * @return bool
     */
    private function add_login_log($uid,$from=0,$regular=0,$dev_md5="")
    {
        $ip_address = $this->input->ip_address();
        $time = time();
        $user_data = array(
            'lasttime' => $time,
            'lastip'   => $ip_address
        );
        $modify_user = $this->user_model->update($uid, $user_data);
        if($modify_user===false)
        {
            return $this->set_error(1002);
        }
        $data = array(
            'uid' => $uid,
            'session_id' => $this->session->session_id,
            'login_ts' => $time,
            'logout_ts' => 0,
            'regular' => $regular,
            'from' => $from,
            'user_agent' => $this->input->server('HTTP_USER_AGENT'),
            'ip' => $ip_address,
            'device_md5'=>$dev_md5
        );

        //新增登陆日志
        $result = $this->user_model->insert_login_log($data);
        if($result===false)
        {
            return $this->set_error(1002);
        }
        else
        {
            $log_id = $this->user_model->get_insert_id();
            $this->user_model->fast_delete_login_error_log($dev_md5);
            return $log_id;
        }
    }

    /**
     * 添加试用账号 (试用功能已取消)
     * @param string $uniqid
     */
    private function add_tryout_user($uniqid=""){
        $uniqid = !empty($uniqid)?$uniqid:Common::uniqid();
        $capacity = $this->config->item("tryout_user_capacity","register");
        $data = array(
            'account_type'=>0,
            'lasttime'	=> time(),
            'lastip'	=> $this->input->ip_address(),
            'uniqid'    => $uniqid,
            'capacity'  => $capacity
        );
        $add = $this->user_model->insert($data);
        if($add===false)
        {
            return $this->set_error(1002);
        }
        else{
            return $this->user_model->get_insert_id();
        }
    }
    /**
     * 试用 (试用功能已取消)
     * @return bool
     */
    public function tryout()
    {
        $user = $this->session->userdata($this->user_info_session_key);
        if($user){
            //已经登录了，要退出 不能用sess_destroy();
            $this->session->unset_userdata($this->user_info_session_key);
        }
        $auto = $this->input->cookie($this->auto_login_cookie_key);
        if(!empty($auto)){
            //如果有自动登录也需要清除
            $this->input->set_cookie($this->auto_login_cookie_key, '', time()-3600,'', '/');
            $this->session->unset_userdata($this->is_tryout_session_key);
        }
        $tryout = $this->input->cookie($this->tryout_cookie_key);
        $uid = false;
        //试用用户存在时，延长试用期
        $tryout_exp = $this->config->item("tryout_exp","register");
        if(!empty($tryout)){

            $this->input->set_cookie($this->tryout_cookie_key, $tryout,$tryout_exp,'', '/');
            //是否真的存在
            $result = $this->user_model->get_user_info_by_uniqid($tryout,"id");
            if(empty($result)){
                //写进用户表 当用户试用过，但是我们的用户表清空的时候会出现
                $uid = $this->add_tryout_user($tryout);
            }
            else{
                $uid = $result['id'];
            }
        } else {
            $tryout = Common::uniqid();
            $uid = $this->add_tryout_user($tryout);
            if($uid===false)
            {
                return $this->set_error(1002);
            }
            else
            {
                $this->input->set_cookie($this->tryout_cookie_key, $tryout,$tryout_exp,'', '/');
            }
        }
        if($uid===false)
        {
            return $this->set_error(1002);
        }
        else
        {
            $this->login_by_uid($uid,0,0);
            //防止 cookie.tryout丢失，导致试用用户判断错误的问题
            $this->session->set_userdata($this->is_tryout_session_key, $tryout);
            return true;
        }
    }

    /**
     * 是否是试用用户 (试用功能已取消)
     * @return mixed
     */
    public function is_tryout(){
        $tryout_sess = $this->session->userdata($this->is_tryout_session_key);
        $tryout_cookie = $this->input->cookie($this->tryout_cookie_key);
        if(!empty($tryout_sess) && $tryout_sess!=$tryout_cookie)
        {
            $tryout_exp = $this->config->item("tryout_exp","register");
            $this->input->set_cookie($this->tryout_cookie_key, $tryout_sess,$tryout_exp,'', '/');
        }
        return !empty($tryout_sess);
    }

    /**
     *  (试用功能已取消)
     * @return mixed
     */
    public function get_tryout()
    {
        return $this->input->cookie($this->tryout_cookie_key);
    }

    /**
     * 删除试用用户 (试用功能已取消)
     */
    public function unset_tryout(){
        $tryout_cookie_key = $this->tryout_cookie_key;
        $tryout = $this->input->cookie($tryout_cookie_key);
        if(!empty($tryout)){
            $this->input->set_cookie($tryout_cookie_key, '', time()-3600,'', '/');
            $this->user_model->update_by_uniqid($tryout,array("uniqid"=>Common::uniqid()));
        }
        $this->session->unset_userdata($this->is_tryout_session_key);
    }



    public function get_login_error_log($dev_md5="")
    {
        if(!empty($dev_md5))
        {
            $where['device_hash'] = Common::time33($dev_md5);
            $where['device_md5']=$dev_md5;
        }
        else{
            $ip = $this->input->ip_address();
            $where['ip_hash'] = Common::time33($ip);
            $where['ip']=$ip;
        }
        return $this->user_model->get_login_error_info($where);
    }

    /**
     *
     * 登录错误次数
     * @param string $dev_md5
     * @return int
     */
    public function get_login_error_num($dev_md5=""){
        if(!empty($dev_md5))
        {
            $where['device_hash'] = Common::time33($dev_md5);
            $where['device_md5']=$dev_md5;
        }
        else{
            $ip = $this->input->ip_address();
            $where['ip_hash'] = Common::time33($ip);
            $where['ip']=$ip;
        }
        //查看数据该ip注册的记录
        $result = $this->user_model->get_login_error_log_info($where,"id,num,lasttime");
        if($result)
        {
            $exp = $this->config->item("login_error_log_exp_time","login");
            if(time() - $result['lasttime'] > $exp){
                $this->user_model->delete_login_error_log(array("id"=>$result['id']));
            } else {
                return (int)$result['num'];
            }
        }
        return 0;
    }

    /**
     * 是否显示验证码
     * @param string $dev_md5 设备hash值
     * @return bool
     */
    public function vcode_required($dev_md5="")
    {
        //一天内同一个ip注册允许免验证码检查次数
        $times = !empty($dev_md5)?$this->config->item("device_ignore_vcode_times","login"):$this->config->item("ip_ignore_vcode_times","login");
        if($times<=0)
        {
            return false;
        }
        $num = $this->get_login_error_num($dev_md5);
        if($num >0 && $num >= $times)
        {
            return $num;
        }
        else
        {
            return false;
        }
    }


    public function add_login_error_log($dev_md5="")
    {
        $ip = $this->input->ip_address();
        $old_num = $this->get_login_error_num($dev_md5);
        $num = $old_num+1;
        $data = array(
            'ip'	=> $ip,
            'ip_hash' => Common::time33($ip),
            'num'	=> $num,
            'device_md5'=>$dev_md5,
            'device_hash'=>Common::time33($dev_md5),
            'lasttime'	=> time()
        );
        if(!empty($dev_md5))
        {
            $where = array(
                'device_hash'=>$data['device_hash'],
                "device_md5" =>$data['device_md5']
            );
        }
        else
        {
            $where=array(
                'ip_hash' => $data['ip_hash'],
                "ip" => $data['ip']
            );
        }
        if($old_num>0){
            $result = $this->user_model->update_login_error_log($where, $data);
        } else {
            $result = $this->user_model->insert_login_error_log($data);
        }
        if($result === false)
        {
            return $this->set_error(1002);
        }
        else
        {
            return true;
        }
    }

    //获取显示的昵称 优先 昵称 》 手机 》 邮箱
    public function get_show_name($row='')
    {
        $row = !empty($row)?$row:$this->get_user_info();
        if($row['nickname']!=""){
            $nickname = $row['nickname'];
        } else if($row['mobile']) {
            $nickname = Common::hide_tel($row['mobile']);
        }
        else
        {
            $nickname = Common::hide_email($row['email']);
        }
        return $nickname;
    }

    /**
     * 快速登录
     * @param $token
     * @param $client_id
     * @param int $opt 1:检查快速登录信息  2:添加快速登录信息 3.检查并快速登录
     * @param string $platform
     * @return bool
     */
    public function fast_login_option($client_id,$token="",$opt=1,$platform="android"){
        $check_require = ($opt==1||$opt==3);
        $add_action = ($opt==2||$opt==3);
        if(!isset($this->fast_login_keys[$platform]) || empty($client_id) || ($check_require && empty($token))){
            return $this->set_error(1003);
        }

        $redis = new Redis();

        $connect = $redis->connect($this->config->item("host","redis"),$this->config->item("port","redis"),$this->config->item("timeout","redis"));
        if(!$connect)
        {
            return $this->set_error(1019);
        }

        $redis_conf_key = $this->fast_login_keys[$platform]."_".md5($client_id);
        //留着备用，修改密码后全端清理快速登陆的方法
        //$redis_key = sprintf($redis_conf_key, $this->login_uid);
        $redis_key = sprintf($redis_conf_key, "");

        $old_data = $redis->get($redis_key);
        $old_data = @json_decode($old_data,true);
        if($check_require && (empty($old_data) || $old_data['token']!=$token)){
            return $this->set_error(5026);
        }
        if($opt==3){
            $this->login_by_uid($old_data['uid']);
        }
        if($add_action){
            $uid = $this->get_user_info("id");
            if(empty($uid)){
                return $this->set_error(1003);
            }
            $data = array(
                "token"=>Common::uniqid(),
                "client_id"=>$client_id,
                "uid"=>$uid
            );
            $set = $redis->setex($redis_key,$this->config->item("fast_login_exp","user_common"),json_encode($data));
            if(!$set)
            {
                return $this->set_error(1019);
            }
        }else{
            $data = $old_data;
        }

        return $data;
    }

    /**
     * 清除 iOS,Android,PC 端快速登陆的fast_token
     * @param $client_id 客户端ID
     * @param $platform 框架(android,ios,pc, 默认android)
     * @return bool|void
     */
    public function fast_login_deprecated($client_id, $platform="") {

        if (in_array($platform, array("android", "ios", "pc"))) {
            $redis_conf_key = $this->fast_login_keys[$platform]."_".md5($client_id);
        } else {
            $platform = "all";
            $redis_conf_key = $this->fast_login_keys[$platform];
        }
        $redis_key = sprintf($redis_conf_key, $this->login_uid);

        $redis = new Redis();

        $connect = $redis->connect($this->config->item("host","redis"),$this->config->item("port","redis"),$this->config->item("timeout","redis"));
        if (!$connect) {
            return $this->set_error(1019);
        }

        if ($platform == "all") {
            $list_keys = $redis->keys($redis_key."*");

            foreach ($list_keys as $fast_login) {
                $set = $redis->del($fast_login);
            }
        } else {
            $set = $redis->del($redis_key);
        }

        if(! $set) {
            return $this->set_error(1019);
        }

        return;
    }

    /**
     * 生成用户gid，方便创建用户目录
     */
    public function get_gid(){
        return md5($this->get_user_info("id")."UNCLONE");
    }

}
